package artiko.ai.posizionamento.rafforzamentoIniziale;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Random;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.Vector;

import jpl.Atom;
import jpl.Query;
import jpl.Term;

import net.yura.domination.engine.core.Continent;
import net.yura.domination.engine.core.Country;

import org.jgrapht.UndirectedGraph;
import org.jgrapht.graph.DefaultEdge;

public class KnowledgeBase {

	private static final String FINAL_STRING = ".\n";
	private FileWriter file;

	public KnowledgeBase(){
		try {
			file = new FileWriter(new File("artiko_resources\\Base_RafforzamentoIniziale\\base.pl"));
			
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
	public void close(){
		try {
			file.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	/** metodo per debugging
	 * 
	 */
	public void increment(){
		try {
			Random s = new Random();
			int a = s.nextInt();
			
			System.out.println("numero generato: " + a);
			file.write("c(m"+a+")" + FINAL_STRING);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	/**
	 * configurazione della mappa
	 * @param map
	 */
	
	public void buildMap(UndirectedGraph<String, DefaultEdge> map){
		try {
//			file.write("confinante(X,Y)" + FINAL_STRING);
//			file.write("confinante(Y,X) :- confinante(X,Y)" + FINAL_STRING);
			
			Set<String> vertici = map.vertexSet();
			for(String a : vertici){
				file.write("territorio(n"+ a+")" + FINAL_STRING);
			}
			
			
			Set<DefaultEdge> edges = map.edgeSet();
			
			for(DefaultEdge edge: edges){
				//System.out.println("confinante(" + new ParserEdge(edge.toString()).getConfinanti()[0] + "," + new ParserEdge(edge.toString()).getConfinanti()[1] + ")" + FINAL_STRING);
				file.write("confinante(n" + new ParserEdge(edge.toString()).getConfinanti()[0] + ", n"  + new ParserEdge(edge.toString()).getConfinanti()[1] + ")" + FINAL_STRING);
			}
			
			
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	/**
	 * configuro i territori che mi appartengono
	 * @param countries
	 */
	public void buildTerritoriesOwned(Vector<String> countriesAmici, Vector<String> countriesNemici){
		for(String a: countriesAmici){
			try {
				
				file.write("amico(" + a + ")" +FINAL_STRING);
			    
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
		for(String b: countriesNemici){
	try {
				
				file.write("nemico(" + b + ")" +FINAL_STRING);
			    
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}	
		}
	}
	
	
	
	public void buildNumberOfArmies(Vector<Integer> armiesTerritories ){
		for(int a = 0; a < armiesTerritories.size(); a++){
			try {
			
				String range = null;
				
				if(armiesTerritories.get(a) <= 1){
					range = "bassa";
				}
				else if(armiesTerritories.get(a) > 1 && armiesTerritories.get(a) <= 3){
					range = "media";
				}
				else{
					range = "alta";
				}
								
				file.write("truppe(n" + a + "," + range + ")" +FINAL_STRING);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	
	
	public void buildBestContinents(Vector<Double> territoriesOwned){
		for(int i = 0; i < territoriesOwned.size(); ++i){
			try {
			
				int color = 0;
				if(i == 0)
					color = 256;
				else if(i == 1)
					color = 16777012;
				else
					color = 32633;
				
				
				String range = null;
				
				if(territoriesOwned.get(i) <= 0.3){
					range = "bassa";
				}
				else if(territoriesOwned.get(i) > 0.3 && territoriesOwned.get(i) <= 0.6){
					range = "media";
				}
				else{
					range = "alta";
				}
					
				//scrivo il continente
				file.write("continente(n" + color+ ")" +FINAL_STRING);
				
				file.write("continenteConvenienza(n" + color + "," + range + ")" +FINAL_STRING);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	
	
	public void buildRules(){
		try {
			
			file.write("continenteDaConq(X) :- continenteConvenienza(X, alta), truppe(Y, bassa), nemico(Y), appartieneA(X,Y)"+ FINAL_STRING);
			file.write("continenteDaConq(X) :- continenteConvenienza(X, media), truppe(Y, bassa), nemico(Y), appartieneA(X,Y)"+ FINAL_STRING);
			file.write("terrAttaccante(X) :- amico(X), confinante(X,Y), nemico(Y), truppe(X,media), truppe(Y,bassa)"+ FINAL_STRING);
			file.write("terrAttaccante(X) :- amico(X), confinante(Y,X), nemico(Y), truppe(X,alta), truppe(Y,bassa)"+ FINAL_STRING);
			
			////////////////////////////
			
			file.write("terrDaEvitare(X) :-  amico(X) , confinante(Y,X) , nemico(Y) ,truppe(Y , alta) , truppe(X,bassa) ");
			file.write("terrDaEvitare(X) :-  amico(X) , confinante(X,Y) , nemico(Y) ,truppe(Y , alta) , truppe(X,bassa) ");
			
			///////////////////////////
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	
	public void buildRelationContinentTerritories(Continent[] continents){
		
		for(int a = 0; a < continents.length; ++a) {
			
			for(Country c : continents[a].getTerritoriesContained()){
				try {
					file.write("appartieneA(n" + (continents[a].getColor()*(-1)) +",n" + (c.getColor() - 1) +")" + FINAL_STRING);
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			
			
		}
		
		
		
		
		
	}
	
	
	
	
	
	// tested
	private class ParserEdge{
		private String edge;
		
		public ParserEdge(String edge){
			this.edge = edge.substring(1, edge.length() - 1); // elimino le parentesi
			
		}
		
		public String[] getConfinanti(){
			String[] array = new String[2];
			
			StringTokenizer tok = new StringTokenizer(edge);
			
			String first = tok.nextToken(" : ");
			
				array[0] = first;
				array[1] = tok.nextToken();
			
			return array;
		}
		
		
	}
}
